if (typeof jQuery == 'undefined') {
    throw new Error('jQuery extend javascript requires jQuery');
}
if (typeof Template7 == 'undefined') {
    throw new Error('jQuery extend javascript requires Template7');
}

$.fn.extend({
    createText: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                verify: true,
                required: false,
                verifyFormatFunction: null,
                verifyFormatParams: [],
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {},
            };
            options = $.extend({}, defaults, options);
            var template =
                '<div class="form-group mb0">' +
                '   <input class="form-control" type="text">' +
                '   <span class="glyphicon form-control-feedback"></span>' +
                '</div>';
            createDom.createTemplate(template).attr('form', '');
            var textDom = createDom.find('input');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            // var value = $.htmlDecode($.toString(domStorage.data(tableName)[fieldName]));
            var value = $.htmlDecode(domStorage.data(tableName)[fieldName]);
            if (options.locked) textDom.attr('locked', '');
            if (options.placeholder) textDom.attr('placeholder', options.placeholder);
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.type,
                verify: options.verify,
                required: options.required,
                value: [],
                index: 0,
            });
            if (!$.isEmpty(options.verifyFormatParams))
                for (var i = 0; i < options.verifyFormatParams.length; i++)
                    createDom.data(options.verifyFormatParams[i].key, options.verifyFormatParams[i].value);
            textDom.val(value).attr(options.attributes).prop({
                readonly: options.readonly,
                disabled: options.disabled,
            });
            textDom.on('change', function () {
                var thisDom = $(this);
                var value = $.toString(thisDom.val());
                if (options.type == enumFormUnitType.decimal) {
                    value = $.accountToNumber(thisDom.val());
                }
                thisDom.verifyClean();
                if (options.verify)
                    if (options.required && $.isEmpty(value)) thisDom.verifyError();
                    else thisDom.verifySuccess();
                if (!$.isEmpty(options.verifyFormatFunction) && $.isFunction(options.verifyFormatFunction)) {
                    var verifyFormatFunctionString = '!options.verifyFormatFunction(value';
                    if (!$.isEmpty(options.verifyFormatParams))
                        for (var i = 0; i < options.verifyFormatParams.length; i++)
                            verifyFormatFunctionString += ', \'' + options.verifyFormatParams[i].value + '\'';
                    verifyFormatFunctionString += ')';
                    if (options.verify && !$.isEmpty(value) && eval(verifyFormatFunctionString)) thisDom.verifyError();
                }
                createDom.saveData(value);
                if (options.type == enumFormUnitType.decimal) {
                    if (!$.isEmpty(thisDom.val())) {
                        thisDom.val($.numberToAccount(thisDom.val()));
                    }
                }
                createDom.trigger('changeCallback', value);
            });
            textDom.trigger('change').verifyClean();
            createDom.trigger('createCallback');
        });
    },
    createString: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.createText(domStorage, fieldValue, $.extend({
                attributes: {
                    minlength: enumMinLength.string,
                    maxlength: enumMaxLength.string,
                },
            }, options, {
                    type: enumFormUnitType.string,
                }));
        });
    },
    createEmail: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.createText(domStorage, fieldValue, $.extend({
                attributes: {
                    minlength: enumMinLength.email,
                    maxlength: enumMaxLength.email,
                },
            }, options, {
                    type: enumFormUnitType.email,
                    verifyFormatFunction: $.isEmail
                }));
        });
    },
    createMobile: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.createText(domStorage, fieldValue, $.extend({
                attributes: {
                    minlength: enumMinLength.mobile,
                    maxlength: enumMaxLength.mobile,
                },
            }, options, {
                    type: enumFormUnitType.mobile,
                    verifyFormatFunction: $.isMobile
                }));
        });
    },
    createTelephone: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.createText(domStorage, fieldValue, $.extend({
                attributes: {
                    minlength: enumMinLength.telephone,
                    maxlength: enumMaxLength.telephone,
                },
            }, options, {
                    type: enumFormUnitType.telephone,
                    verifyFormatFunction: $.isTelephone
                }));
        });
    },
    createInteger: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.createText(domStorage, fieldValue, $.extend({
                attributes: {
                    minlength: enumMinLength.integer,
                    maxlength: enumMaxLength.integer,
                },
            }, options, {
                    type: enumFormUnitType.integer,
                    verifyFormatFunction: $.isInteger,
                    verifyFormatParams: [{
                        key: 'range',
                        value: (options && options.range) || '+',
                    }]
                }));
        });
    },
    createDecimal: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.createText(domStorage, fieldValue, $.extend({
                attributes: {
                    minlength: enumMinLength.decimal,
                    maxlength: enumMaxLength.decimal,
                },
            }, options, {
                    type: enumFormUnitType.decimal,
                    verifyFormatFunction: $.isDecimal,
                    verifyFormatParams: [{
                        key: 'digit',
                        value: (options && options.digit) || 2
                    }, {
                        key: 'range',
                        value: (options && options.range) || '+',
                    }]
                }));
        });
    },
    createDatepicker: function (domStorage, fieldValue, options) {
        return this.each(function () {
            if (typeof $.fn.datepicker == 'undefined') throw new Error('jQuery extend javascript requires bootstrap datepicker');
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.date,
                verify: true,
                required: false,
                locked: createDom.is('[locked]'),
                readonly: true,
                disabled: false,
                attributes: {
                    minlength: enumMinLength.date,
                    maxlength: enumMaxLength.date,
                },
                datepickerOptions: $.extend({}, _datepicker),
            };
            options.datepickerOptions = $.extend({}, defaults.datepickerOptions, options.datepickerOptions);
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.date,
            });
            var template =
                '<div class="form-group mb0">' +
                ' <input class="form-control input-append date" type="text">' +
                ' <span class="glyphicon form-control-feedback"></span>' +
                '</div>';
            createDom.createTemplate(template).attr('form', '');
            createDom.createUnit('<i class="fa fa-calendar"></i>', '<i class="fa fa-close"></i>');
            var datepickerDom = createDom.find('input');
            var calendarDom = createDom.find('.fa-calendar').parent();
            var closeDom = createDom.find('.fa-close').parent();
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            // var value = $.htmlDecode($.toString(domStorage.data(tableName)[fieldName]));
            var value = $.htmlDecode(domStorage.data(tableName)[fieldName]);
            if (options.locked) datepickerDom.attr('locked', '');
            if (options.placeholder) datepickerDom.attr('placeholder', options.placeholder);
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.type,
                verify: options.verify,
                required: options.required,
                value: [],
                index: 0,
            });
            datepickerDom.val(value).attr(options.attributes).prop({
                readonly: options.readonly,
                disabled: options.disabled,
            });
            datepickerDom.datepicker(options.datepickerOptions);
            datepickerDom.on('changeDate', function () {
                var thisDom = $(this);
                var value = $.toString(thisDom.val());
                thisDom.verifyClean();
                if (options.verify && options.required && $.isEmpty(value)) thisDom.verifyError();
                else thisDom.verifySuccess();
                createDom.saveData(value);
                createDom.trigger('changeCallback', value);
            });
            calendarDom.on('click', function () {
                if (!datepickerDom.prop('disabled')) datepickerDom.datepicker('show');
            });
            closeDom.on('click', function () {
                if (!datepickerDom.prop('disabled')) datepickerDom.val(null).datepicker('update').trigger('changeDate');
            });
            datepickerDom.trigger('changeDate').verifyClean();
            createDom.trigger('createCallback');
        });
    },
    createDoubleDatepicker: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.doubleDate,
                verify: true,
                required: false,
                locked: createDom.is('[locked]'),
                readonly: true,
                disabled: false,
                startAttributes: {
                    minlength: enumMinLength.date,
                    maxlength: enumMaxLength.date,
                },
                endAttributes: {
                    minlength: enumMinLength.date,
                    maxlength: enumMaxLength.date,
                },
                startDatepickerOptions: {},
                endDatepickerOptions: {},
            };
            options = $.extend({}, defaults, options);
            var template =
                '<table class="col-xs-12">' +
                ' <tbody>' +
                '   <tr>' +
                '     <td width="50%" start>' +
                '     </td>' +
                '     <td class="text-center">' +
                '       <i class="fa fa-exchange ml10 mr10"></i>' +
                '     </td>' +
                '     <td width="50%" end>' +
                '     </td>' +
                '   </tr>' +
                ' </tbody>' +
                '</table>';
            createDom.createTemplate(template).attr('form', '');
            var startDom = createDom.find('td[start]');
            var endDom = createDom.find('td[end]');
            if (options.locked) {
                startDom.attr('locked', '');
                endDom.attr('locked', '');
            }
            startDom.createDatepicker(domStorage, fieldValue.split(',')[0].trim(), $.extend({}, options, {
                type: enumFormUnitType.date,
                datepickerOptions: options.startDatepickerOptions,
            }));
            endDom.createDatepicker(domStorage, fieldValue.split(',')[1].trim(), $.extend({}, options, {
                type: enumFormUnitType.date,
                datepickerOptions: options.startDatepickerOptions,
            }));
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.type,
                verify: options.verify,
                required: options.required,
            });
            var startDatepickerDom = startDom.find('input');
            var startCalendarDom = startDom.find('.fa-calendar');
            var startCloseDom = startDom.find('.fa-close');
            var endDatepickerDom = endDom.find('input');
            var endCalendarDom = endDom.find('.fa-calendar');
            var endCloseDom = endDom.find('.fa-close');
            startDom.on('changeCallback', function () {
                endDatepickerDom.datepicker('setStartDate', startDatepickerDom.val());
                if ($.isEmpty(endDatepickerDom.val())) endDatepickerDom.datepicker('show');
            });
            endDom.on('changeCallback', function () {
                startDatepickerDom.datepicker('setEndDate', endDatepickerDom.val());
                if ($.isEmpty(startDatepickerDom.val())) startDatepickerDom.datepicker('show');
            });
        });
    },
    createSelect: function (domStorage, fieldValue, fieldText, optionList, options) {
        return this.each(function () {
            if ($.isArray(fieldText)) {
                options = optionList;
                optionList = fieldText;
                fieldText = '';
            }
            optionList = [].concat(optionList);
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.select,
                verify: true,
                required: false,
                firstOption: _defaultSelect,
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {},
                isOther: false,
            };
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.select,
            });
            var template =
                '<div class="form-group mb0">' +
                ' <select class="form-control"></select>' +
                ' <span class="glyphicon form-control-feedback r25"></span>' +
                '</div>';
            createDom.createTemplate(template).attr('form', '');
            var selectDom = createDom.find('select');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = $.htmlDecode(domStorage.data(tableName)[fieldName]);
            var textTableName = fieldText.split('.')[0];
            var textFieldName = fieldText.split('.')[1];
            if ($.isEmpty(domStorage.data(textTableName))) domStorage.data(textTableName, {});
            var text = $.htmlDecode(domStorage.data(textTableName)[textFieldName]);
            selectDom.createOptionList(optionList, options.firstOption);
            if (options.locked) selectDom.attr('locked', '');
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                fieldText: fieldText,
                type: options.type,
                verify: options.verify,
                required: options.required,
                value: [],
                text: [],
                index: 0,
                firstOption: options.firstOption,
            });
            selectDom.val(value).attr(options.attributes).prop({
                readonly: options.readonly,
                disabled: options.disabled,
            });
            selectDom.on('change', function () {
                var thisDom = $(this);
                var value = $.toString(thisDom.val());
                var text = $.toString(thisDom.find('option:selected').text());
                thisDom.verifyClean();
                if (options.verify)
                    if (options.required && $.isEmpty(value)) thisDom.verifyError();
                    else thisDom.verifySuccess();
                createDom.saveData(value, text);
                createDom.trigger('changeCallback', [value, text]);
            });
            selectDom.trigger('change').verifyClean();
            createDom.trigger('createCallback');
        });
    },
    createSelectOther: function (domStorage, fieldValue, fieldText, optionList, options) {
        return this.each(function () {
            optionList = [].concat(optionList);
            var createDom = $(this);
            var defaults = {
                verify: true,
                required: false,
                otherVerify: true,
                otherRequired: false,
                firstOption: _defaultSelect,
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {},
                otherAttributes: {},
            };
            options = $.extend({}, defaults, options);
            var template =
                '<div class="component-select-other">' +
                ' <div class="component-select-other-select"></div>' +
                ' <div class="component-select-other-other"></div>' +
                '</div>';
            createDom.createTemplate(template).attr('form', '');
            var valueTableName = fieldValue.split('.')[0];
            var valueFieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(valueTableName))) domStorage.data(valueTableName, {});
            var value = $.htmlDecode(domStorage.data(valueTableName)[valueFieldName]);
            var textTableName = fieldText.split('.')[0];
            var textFieldName = fieldText.split('.')[1];
            if ($.isEmpty(domStorage.data(textTableName))) domStorage.data(textTableName, {});
            var text = $.htmlDecode(domStorage.data(textTableName)[textFieldName]);
            var selectDom = createDom.find('.component-select-other-select');
            var inputDom = createDom.find('.component-select-other-other');
            optionList.push(_otherSelect);
            selectDom.createSelect(domStorage, fieldValue, optionList, $.extend({}, options));
            inputDom.createString(domStorage, fieldText, $.extend({
                verify: options.otherVerify,
                required: options.otherRequired,
                locked: options.locked,
                readonly: options.readonly,
                disabled: options.disabled,
                attributes: options.otherAttributes,
            }));
            selectDom.on('changeCallback', function (event, value) {
                if ($.toNumber(value) === _otherSelect.key) {
                    selectDom.css({ width: '50%' });
                    inputDom.removeClass('dn');
                    var isOtherText = true;
                    if (isOtherText == _defaultSelect.value ||
                        isOtherText == _allSelect.value ||
                        isOtherText == _otherSelect.value) {
                        isOtherText = false;
                    }
                    for (var i = 0; i < optionList.length; i++) {
                        if (text == optionList[i].value) isOtherText = false;
                    }
                    if (!isOtherText) text = '';
                } else {
                    if (!$.isEmpty(value)) {
                        text = selectDom.find('option:selected').text();
                    } else {
                        text = '';
                    }
                    selectDom.css({ width: '100%' });
                    inputDom.addClass('dn');
                }
                inputDom.findFormUnit().val(text).trigger('change').verifyClean();
            });
            selectDom.findFormUnit().trigger('change').verifyClean();
        });
    },
    createSelectOtherAndNo: function (domStorage, fieldValue, fieldText, optionList, options) {
        return this.each(function () {
            optionList = [].concat(optionList);
            var createDom = $(this);
            var defaults = {
                verify: true,
                required: false,
                otherVerify: true,
                otherRequired: false,
                firstOption: _defaultSelect,
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {},
                otherAttributes: {},
            };
            options = $.extend({}, defaults, options);
            var template =
                '<div class="component-select-other">' +
                ' <div class="component-select-other-select"></div>' +
                ' <div class="component-select-other-other"></div>' +
                '</div>';
            createDom.createTemplate(template).attr('form', '');
            var valueTableName = fieldValue.split('.')[0];
            var valueFieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(valueTableName))) domStorage.data(valueTableName, {});
            var value = $.htmlDecode(domStorage.data(valueTableName)[valueFieldName]);
            var textTableName = fieldText.split('.')[0];
            var textFieldName = fieldText.split('.')[1];
            if ($.isEmpty(domStorage.data(textTableName))) domStorage.data(textTableName, {});
            var text = $.htmlDecode(domStorage.data(textTableName)[textFieldName]);
            var selectDom = createDom.find('.component-select-other-select');
            var inputDom = createDom.find('.component-select-other-other');
            optionList.push(_otherSelect);
            optionList.push(_noSelect);
            selectDom.createSelect(domStorage, fieldValue, optionList, $.extend({}, options));
            inputDom.createString(domStorage, fieldText, $.extend({
                verify: options.otherVerify,
                required: options.otherRequired,
                locked: options.locked,
                readonly: options.readonly,
                disabled: options.disabled,
                attributes: options.otherAttributes,
            }));
            selectDom.on('changeCallback', function (event, value) {
                if ($.toNumber(value) === _otherSelect.key) {
                    selectDom.css({ width: '50%' });
                    inputDom.removeClass('dn');
                    var isOtherText = true;
                    if (isOtherText == _defaultSelect.value ||
                        isOtherText == _allSelect.value ||
                        isOtherText == _otherSelect.value) {
                        isOtherText = false;
                    }
                    for (var i = 0; i < optionList.length; i++) {
                        if (text == optionList[i].value) isOtherText = false;
                    }
                    if (!isOtherText) text = '';
                    // text = '';
                } else {
                    if (!$.isEmpty(value)) {
                        text = selectDom.find('option:selected').text();
                    } else {
                        text = '';
                    }
                    selectDom.css({ width: '100%' });
                    inputDom.addClass('dn');
                }
                inputDom.findFormUnit().val(text).trigger('change').verifyClean();
            });
            selectDom.findFormUnit().trigger('change').verifyClean();
        });
    },
    createLocation: function (domStorage, fieldProvinceValue, fieldProvinceText, fieldCityValue, fieldCityText, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                verify: true,
                required: false,
                firstOption: _defaultSelect,
                cityVerify: true,
                cityRequired: false,
                cityFirstOption: _defaultSelect,
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {},
                cityAttributes: {},
            };
            options = $.extend({}, defaults, options);
            var template =
                '<div class="component-location">' +
                ' <div class="component-location-province"></div>' +
                ' <div class="component-location-city"></div>' +
                '</div>';
            createDom.createTemplate(template).attr('form', '');
            var provinceDom = createDom.find('.component-location-province');
            var cityDom = createDom.find('.component-location-city');
            provinceDom.createSelect(domStorage, fieldProvinceValue, fieldProvinceText, _provinceCityList, $.extend({}, options));
            provinceDom.on('changeCallback', function (event, value, text) {
                var thisDom = $(this);
                var data = thisDom.find('option:selected').data().data;
                var citySelectOptions = $.extend({}, options, {
                    verify: options.cityVerify,
                    required: options.cityRequired,
                    firstOption: options.cityFirstOption,
                    locked: options.locked,
                    readonly: options.readonly,
                    disabled: options.disabled,
                    attributes: options.cityAttributes,
                });
                if ($.isEmpty(value)) {
                    cityDom.empty().createSelect(domStorage, fieldCityValue, fieldCityText, [], citySelectOptions);
                } else {
                    cityDom.empty().createSelectOther(domStorage, fieldCityValue, fieldCityText, data.cityList, citySelectOptions);
                }
            });
            provinceDom.findFormUnit().trigger('change').verifyClean();
            cityDom.on('changeCallback', function (event, value) {
                if ($.toNumber(value) === _otherSelect.key) {
                    provinceDom.css({ width: '33%', maxWidth: 200 });
                    cityDom.css({ width: '67%', maxWidth: 400 });
                } else {
                    provinceDom.css({ width: '50%', maxWith: 300 });
                    cityDom.css({ width: '50%', maxWidth: 300 });
                }
            });
            cityDom.findFormUnit().trigger('change').verifyClean();
        });
    },
    createRadio: function (domStorage, fieldValue, fieldText, groupList, options) {
        return this.each(function () {
            if ($.isArray(fieldText)) {
                options = groupList;
                groupList = fieldText;
                fieldText = '';
            }
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.radio,
                locked: createDom.is('[locked]'),
                disabled: false,
                attributes: {},
            };
            options = $.extend({}, defaults, options);
            var guid = $.getGuid();
            var template =
                '<label class="radio-inline mr10 vat" data>' +
                ' <input type="radio" name="' + guid + '" value="{{key}}">{{value}}' +
                '</label>';
            createDom.createListTemplate(template, groupList).attr('form', '');
            var radioListDom = createDom.find(':radio');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = $.htmlDecode(domStorage.data(tableName)[fieldName]);
            if (options.locked) selectDom.attr('locked', '');
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                fieldText: fieldText,
                type: options.type,
                value: [],
                text: [],
                index: 0,
            });
            radioListDom.filter('[value=' + value + ']').prop('checked', true);
            radioListDom.attr(options.attributes);
            if ($.isBoolean(options.disabled)) radioListDom.prop('disabled', options.disabled);
            if ($.isArray(options.disabled))
                for (var i = 0; i < options.disabled.length; i++)
                    radioListDom.eq(options.disabled[i]).prop('disabled', true).parent().addClass('disabled');
            radioListDom.on('change', function () {
                var thisDom = $(this);
                var isChecked = thisDom.is(':checked');
                var value = $.toString(thisDom.val());
                var text = $.toString(thisDom.parent().data('data').value);
                if (!isChecked) return;
                createDom.saveData(value, text);
                createDom.trigger('changeCallback', value);
            });
            radioListDom.eq(0).prop('checked', true).trigger('change').verifyClean();
            createDom.trigger('createCallback');
        });
    },
    createCheckbox: function (domStorage, fieldValue, fieldText, groupList, options) {
        return this.each(function () {
            if ($.isArray(fieldText)) {
                options = groupList;
                groupList = fieldText;
                fieldText = '';
            }
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.checkbox,
                locked: createDom.is('[locked]'),
                allSelected: false,
                disabled: false,
                attributes: {},
            };
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.checkbox,
            });
            var guid = $.getGuid();
            var template =
                '<label class="checkbox-inline mr10 vat" data>' +
                ' <input type="checkbox" name="' + guid + '" value="{{key}}">{{value}}' +
                '</label>';
            if (options.allSelected) createDom.createTemplate(template, {
                key: _allSelect.key,
                value: _allSelect.value
            });
            createDom.createListTemplate(template, groupList).attr('form', '');
            var allSelectDom = options.allSelected ? createDom.find(':checkbox:eq(0)') : null;
            var checkboxListDom = options.allSelected ? createDom.find(':checkbox:gt(0)') : createDom.find(':checkbox');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = $.toArray(domStorage.data(tableName)[fieldName]);
            if (options.locked) checkboxListDom.attr('locked', '');
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                fieldText: fieldText,
                type: options.type,
                value: [],
                text: [],
                index: 0
            });
            checkboxListDom.attr(options.attributes);
            var selectedCount = 0;
            for (var i = 0; i < value.length; i++) {
                for (var j = 0; j < checkboxListDom.length; j++) {
                    if (value[i] == checkboxListDom.eq(j).val()) {
                        checkboxListDom.eq(j).prop('checked', true);
                        selectedCount++;
                        break;
                    }
                }

                if (selectedCount === checkboxListDom.length && options.allSelected)
                    allSelectDom.prop('checked', true);
            }

            if ($.isBoolean(options.disabled)) checkboxListDom.prop('disabled', options.disabled);
            if ($.isArray(options.disabled))
                for (var i = 0; i < options.disabled.length; i++)
                    for (var j = 0; j < checkboxListDom.length; j++)
                        if (options.disabled[i] == checkboxListDom.eq(j).val()) checkboxListDom.eq(j).prop('disabled', true).parent().addClass('disabled');
            if (!$.isEmpty(allSelectDom))
                allSelectDom.on('change', function () {
                    var thisDom = $(this);
                    var isChecked = thisDom.is(':checked');
                    var value = [];
                    var checkboxListDom = createDom.find(':checkbox:gt(0)');
                    checkboxListDom.prop('checked', isChecked);
                    for (var i = 0; i < checkboxListDom.length; i++)
                        if (checkboxListDom.eq(i).is(':checked')) value.push($.toString(checkboxListDom.eq(i).val()));
                    createDom.saveData(value);
                    createDom.trigger('changeCallback', value);
                });
            checkboxListDom.on('change', function () {
                var thisDom = $(this);
                var isChecked = thisDom.is(':checked');
                var value = [];
                var text = [];
                for (var i = 0; i < checkboxListDom.length; i++)
                    if (checkboxListDom.eq(i).val() != _allSelect.key && checkboxListDom.eq(i).is(':checked')) (value.push($.toString(checkboxListDom.eq(i).val()))) && (text.push(checkboxListDom.eq(i).parent().data('data').value));
                if (options.allSelected && (checkboxListDom.length == checkboxListDom.filter(':checked').length)) allSelectDom.prop('checked', true);
                else {
                    if (!$.isEmpty(allSelectDom)) allSelectDom.prop('checked', false);
                }
                createDom.saveData(value, text);
                createDom.trigger('changeCallback', value);
            });
            checkboxListDom.eq(0).trigger('change').verifyClean();
            createDom.trigger('createCallback');
        });
    },
    createSingleCheckbox: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.singleCheckbox,
                locked: createDom.is('[locked]'),
                reverse: false,
                isNumber: false,
                text: '是',
                disabled: false,
                attributes: {},
            };
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.singleCheckbox,
            });
            var guid = $.getGuid();
            var template =
                '<label class="checkbox-inline mr10 vat" data>' +
                ' <input type="checkbox" name="' + guid + '">' + options.text +
                '</label>';
            createDom.createTemplate(template).attr('form', '');
            var checkboxDom = createDom.find(':checkbox');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = domStorage.data(tableName)[fieldName];
            if (options.locked) checkboxDom.attr('locked', '');
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.type,
                reverse: options.reverse,
                isNumber: options.isNumber,
                value: [],
                index: 0
            });
            if (options.isNumber && options.reverse && $.isZero(value) ||
                options.isNumber && !options.reverse && !$.isZero(value) ||
                !options.isNumber && options.reverse && !$.toBoolean(value) ||
                !options.isNumber && !options.reverse && $.toBoolean(value)) checkboxDom.prop('checked', true);
            else checkboxDom.prop('checked', false);
            checkboxDom.attr(options.attributes).prop('disabled', options.disabled);
            checkboxDom.on('change', function () {
                var thisDom = $(this);
                var isChecked = thisDom.is(':checked');
                var value;
                if ((options.isNumber && options.reverse && !isChecked) ||
                    (options.isNumber && !options.reverse && isChecked)) value = 1;
                if ((options.isNumber && options.reverse && isChecked) ||
                    (options.isNumber && !options.reverse && !isChecked)) value = 0;
                if ((!options.isNumber && options.reverse && !isChecked) ||
                    (!options.isNumber && !options.reverse && isChecked)) value = true;
                if ((!options.isNumber && options.reverse && isChecked) ||
                    (!options.isNumber && !options.reverse && !isChecked)) value = false;
                createDom.saveData(value);
                createDom.trigger('changeCallback', value);
            });
            checkboxDom.trigger('change').verifyClean();
            createDom.trigger('createCallback');
        });
    },
    createTextarea: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.textarea,
                verify: true,
                required: false,
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {
                    minlength: enumMinLength.textarea,
                    maxlength: enumMaxLength.textarea,
                    rows: 5,
                },
            };
            options = $.extend({}, defaults, options);
            var template =
                '<div class="form-group mb0">' +
                ' <textarea class="form-control"></textarea>' +
                ' <span class="glyphicon form-control-feedback"></span>' +
                '</div>';
            createDom.createTemplate(template).attr('form', '');
            var textareaDom = createDom.find('textarea');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = $.htmlDecode($.toString(domStorage.data(tableName)[fieldName]));
            // var value = $.htmlDecode(domStorage.data(tableName)[fieldName]);
            if (options.locked) textareaDom.attr('locked', '');
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.type,
                verify: options.verify,
                required: options.required,
                value: [],
                index: 0,
            });
            textareaDom.val(value).attr(options.attributes).prop({
                readonly: options.readonly,
                disabled: options.disabled,
            });
            textareaDom.on('change', function () {
                var thisDom = $(this);
                var value = $.toString(thisDom.val());
                thisDom.verifyClean();
                if (options.verify)
                    if (options.required && $.isEmpty(value)) thisDom.verifyError();
                    else thisDom.verifySuccess();
                createDom.saveData(value);
                createDom.trigger('changeCallback', value);
            });
            textareaDom.trigger('change').verifyClean();
            createDom.trigger('createCallback');
        });
    },
    createAttachment: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.attachment,
                locked: createDom.is('[locked]'),
                disabled: false,
                attributes: {},
                template: '' +
                    '<tr data>' +
                    ' <td class="nbd vam">' +
                    ' <a href="' + _apiPath + '/Elancos/downloadAttachments?container={{format container}}&name={{format name}}' + '">{{format originalFilename}}</a>' +
                    ' </td>' +
                    ' <td class="nbd vam" width="70">{{format size \'$.toSize\'}}</td>' +
                    ' <td class="nbd" width="70">' +
                    '   <button class="btn upload-clear" type="button" delete>删除</button>' +
                    ' </td>' +
                    '</tr>',
            };
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.attachment,
            });
            var guid = $.getGuid();
            var template =
                '<table class="table mb0">' +
                ' <tbody>' +
                '   <tr>' +
                '     <td class="nbd">' +
                '       <div class="form-group mb0">' +
                '         <input id="' + guid + '" class="form-control" name="' + guid + '" type="file">' +
                '         <span class="glyphicon form-control-feedback"></span>' +
                '       </div>' +
                '     </td>' +
                '     <td class="nbd" width="70">' +
                '       <button class="btn btn-default common-form-btn" type="button" upload>上传</button>' +
                '     </td>' +
                '   </tr>' +
                '   <tr>' +
                '     <td class="npd nbd" colspan="2">' +
                '       <table class="table table-attachment mb0">' +
                '         <tbody>' +
                '         </tbody>' +
                '       </table>' +
                '     </td>' +
                '   </tr>' +
                ' </tbody>' +
                '</table>';
            createDom.createTemplate(template).attr('form', '').addClass('npd');
            var fileDom = createDom.find(':file');
            var uploadDom = createDom.find('.btn[upload]');
            var attachmentDom = createDom.find('.table-attachment tbody');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = $.toArray(domStorage.data(tableName)[fieldName]);
            if (options.locked) textareaDom.attr('locked', '');
            createDom.data({
                template: options.template,
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.type,
                value: [value],
                index: 0,
            });
            fileDom.attr(options.attributes).prop({
                disabled: options.disabled,
            });
            for (var i = 0; i < value.length; i++)
                attachmentDom.createTemplate(options.template, value[i]);
            uploadDom.on('click', function () {
                if ($.isEmpty(fileDom.val())) return fileDom.verifyError().verifyHelp(_enumMessage.noAttachment);
                fileDom.verifyClean();
                fileDom.upload(function (data) {
                    fileDom.val(null);
                    attachmentDom.createTemplate(options.template, data);
                    createDom.saveData([].concat(createDom.data().value[createDom.data().index]).concat([data]));
                    createDom.trigger('uploadCallback');
                });
            });
            createDom.on('click', '.btn[delete]', function () {
                var thisDom = $(this);
                var value = [].concat(createDom.data().value[createDom.data().index]);
                var attachmentDomList = createDom.find('.table-attachment tr');
                for (var i = 0; i < attachmentDomList.length; i++) {
                    if (attachmentDomList[i] == thisDom.parent().parent()[0]) {
                        value.splice(i, 1);
                    }
                }
                thisDom.parent().parent().remove();
                createDom.saveData(value);
            });
            createDom.trigger('createCallback');
        });
    },
    createStandardAttachment: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.attachment,
                locked: createDom.is('[locked]'),
                disabled: false,
                attributes: {},
                template: '' +
                    '<tr data>' +
                    ' <td class="nbd vam">' +
                    ' <a href="' + _apiPath + '/Elancos/downloadAttachments?container={{format container}}&name={{format name}}' + '">{{format originalFilename}}</a>' +
                    ' </td>' +
                    ' <td class="nbd vam" width="70">{{format size \'$.toSize\'}}</td>' +
                    ' <td class="nbd" width="70">' +
                    '   <button class="btn upload-clear" type="button" delete>删除</button>' +
                    ' </td>' +
                    '</tr>',
            };
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.attachment,
            });
            var guid = $.getGuid();
            var template =
                '<table class="table component-table-attechment mb0">' +
                ' <tbody>' +
                '   <tr>' +
                '     <td class="nbd">' +
                '       <div class="form-group mb0">' +
                '         <input id="' + guid + '" class="form-control" name="' + guid + '" type="file">' +
                '         <span class="glyphicon form-control-feedback"></span>' +
                '       </div>' +
                '     </td>' +
                '     <td class="nbd" width="70">' +
                '       <button class="btn btn-default common-form-btn" type="button" upload>上传</button>' +
                '     </td>' +
                '   </tr>' +
                '   <tr>' +
                '     <td class="npd nbd" colspan="2">' +
                '       <table class="table table-attachment mb0">' +
                '         <tbody>' +
                '         </tbody>' +
                '       </table>' +
                '     </td>' +
                '   </tr>' +
                ' </tbody>' +
                '</table>';
            createDom.createTemplate(template).attr('form', '').addClass('npd');
            var fileDom = createDom.find(':file');
            var uploadDom = createDom.find('.btn[upload]');
            var attachmentDom = createDom.find('.table-attachment tbody');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = $.toArray(domStorage.data(tableName)[fieldName]);
            if (options.locked) textareaDom.attr('locked', '');
            createDom.data({
                template: options.template,
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.type,
                value: [value],
                index: 0,
            });
            fileDom.attr(options.attributes).prop({
                disabled: options.disabled,
            });
            for (var i = 0; i < value.length; i++)
                attachmentDom.createTemplate(options.template, value[i]);
            uploadDom.on('click', function () {
                if ($.isEmpty(fileDom.val())) return fileDom.verifyError().verifyHelp(_enumMessage.noAttachment);
                fileDom.verifyClean();
                fileDom.upload(function (data) {
                    fileDom.val(null);
                    attachmentDom.createTemplate(options.template, data);
                    createDom.saveData([].concat(createDom.data().value[createDom.data().index]).concat([data]));
                    createDom.trigger('uploadCallback');
                });
            });
            createDom.on('click', '.btn[delete]', function () {
                var thisDom = $(this);
                var value = [].concat(createDom.data().value[createDom.data().index]);
                var attachmentDomList = createDom.find('.table-attachment tr');
                for (var i = 0; i < attachmentDomList.length; i++) {
                    if (attachmentDomList[i] == thisDom.parent().parent()[0]) {
                        value.splice(i, 1);
                    }
                }
                thisDom.parent().parent().remove();
                createDom.saveData(value);
            });
            createDom.trigger('createCallback');
        });
    },
    createUser: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.user,
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {},
                buttonAttributes: {},
                format: '{{format employeeId \'$.toString\'}} / {{format chineseName \'$.toString\'}}',
                single: true,
                displayInTextBox: false,
                methodName: 'searchUserListByQuery',
                getMethodParams: function (keyword) {
                    return $.extend({}, {
                        query: keyword,
                    });
                },
                noUserMessage: _enumMessage.noUser,
                noKeywordMessage: _enumMessage.noKeyword,
            };
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.user,
            });
            var template =
                '<table class="table component-table-user mb0" user>' +
                ' <tbody>' +
                '   <tr>' +
                '     <td class="nbd" keyword></td>' +
                '     <td class="nbd" width="100">' +
                '       <button class="btn btn-default common-form-btn" type="button" search>搜索</button>' +
                '     </td>' +
                '   </tr>' +
                ' </tbody>' +
                '</table>';
            createDom.createTemplate(template).attr('form', '').addClass('npd');
            var id = $.getGuid();
            var contentDom = $('.content');
            var userDom = createDom.find('table[user]');
            var keywordDom = createDom.find('td[keyword]');
            var searchDom = createDom.find('.btn[search]');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            var offsetTop = 0;
            var offsetLeft = 0;
            var userItemTemplate = '' +
                '   <tr data>' +
                '     <td class="nbd vam">' + options.format + '</td>' +
                '     <td class="nbd" width="100">' +
                '       <button class="btn btn-default common-form-btn" type="button" delete>删除</button>' +
                '     </td>' +
                '   </tr>';
            var relevanceListTemplate = '' +
                '<div id="{{id}}" style="position: absolute; height: 200px; overflow: auto;" relevance>' +
                '   <ul class="list-group">' +
                '   </ul>' +
                '</div>';
            var relevanceItemTemplate = '<li class="list-group-item" data>' + options.format + '</li>';
            if ($.isEmpty(domStorage.data(tableName))) {
                if (options.single) domStorage.data(tableName, {});
                else domStorage.data(tableName, []);
            }
            var value = domStorage.data(tableName)[fieldName];
            if (options.single) {
                value = $.toObject(value);
            } else {
                value = $.toArray(value);
            }
            if (options.locked) searchDom.attr('locked', '');
            createDom.data({
                format: options.format,
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.user,
                value: [value],
                index: 0,
            });
            searchDom.attr(options.buttonAttributes).prop({
                disabled: options.disabled,
            });
            keywordDom.createString(userDom, 'params.keyword', $.extend({}, options));
            var keywordInputDom = keywordDom.find('input');
            if (!$.isEmpty(value)) {
                if (options.single) {
                    if (options.displayInTextBox) {
                        keywordInputDom.val(value.employeeId + ' / ' + value.chineseName);
                        userDom.data().params.keyword = value.employeeId;
                    }
                    else userDom.find('tbody').createTemplate(userItemTemplate, value);
                } else {
                    if (options.displayInTextBox) {
                        userDom.data().params.keyword = value.employeeId;
                        keywordInputDom.val(value[0].employeeId + ' / ' + value[0].chineseName);
                    }
                    else {
                        for (var i = 0; i < value.length; i++)
                            userDom.find('tbody').createTemplate(userItemTemplate, value[i]);
                    }
                }
            } else {
                if (options.single) {
                    domStorage.data(tableName)[fieldName] = {};
                } else {
                    domStorage.data(tableName)[fieldName] = [];
                }
            }
            setTimeout(function () {
                offsetTop = keywordInputDom.position().top + 40;
                offsetLeft = keywordInputDom.position().left;
            }, 1);
            searchDom.on('click', function () {
                var keyword = userDom.data().params.keyword.split('/')[0].trim();
                if ($.isEmpty(keyword)) return keywordDom.verifyErrorAndHelp(options.noKeywordMessage);
                var getMethodParams = function (keyword) {
                    if ($.isEmpty(options.getMethodParams) || !$.isFunction(options.getMethodParams)) return {};
                    if ($.isEmpty(options.getMethodParams(keyword)) || !$.isObject(options.getMethodParams(keyword))) return {};
                    return options.getMethodParams(keyword);
                }
                var params = $.extend(params, {
                    customMethodName: options.methodName,
                    customMethodParams: getMethodParams(keyword),
                });
                console.log(params)
                $.post(_apiPath + '/eLancos/customMethod', params)
                    .then(function (data) {
                        if ($.isEmpty(data)) return $.alert(options.noUserMessage);
                        contentDom.createTemplate(relevanceListTemplate, { id: id });
                        contentDom.find(' div[relevance]:last .list-group').createListTemplate(relevanceItemTemplate, data);
                        contentDom.find(' div[relevance]:last').css({
                            top: offsetTop,
                            left: offsetLeft,
                            width: keywordInputDom.outerWidth(),
                        });
                        return false;
                    });
            });
            $('body').on('click', function () {
                if ($('div[relevance]').length != 0) $('div[relevance]').remove();
            });
            $('body').on('click', '#' + id + ' .list-group-item', function () {
                var thisDom = $(this);
                var relevanceListDom = thisDom.parents('div[relevance]');
                var data = thisDom.data().data;
                if (options.single) userDom.find('tbody tr[data]').remove();
                if (options.displayInTextBox) keywordDom.findFormUnit().val(data.employeeId + ' / ' + data.chineseName).trigger('change').verifyClean();
                else userDom.find('tbody').createTemplate(userItemTemplate, data);
                createDom.saveData(data);
                relevanceListDom.remove();
                if (!options.displayInTextBox) keywordDom.findFormUnit().val(null).trigger('change').verifyClean();
                createDom.trigger('selectUserCallback', data);
                return false;
            });
            createDom.on('click', '.btn[delete]', function () {
                var thisDom = $(this);
                thisDom.parents('tr[data]').remove();
                createDom.saveData({});
            });
            createDom.trigger('createCallback');
        });
    },
    createUserStandard: function (domStorage, fieldValue, options) {
        return this.each(function () {
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.user,
                locked: createDom.is('[locked]'),
                readonly: false,
                disabled: false,
                attributes: {},
                buttonAttributes: {},
                format: '{{format employeeId \'$.toString\'}} / {{format chineseName \'$.toString\'}}',
                single: true,
                displayInTextBox: false,
                methodName: 'searchUserListByQuery',
                getMethodParams: function (keyword) {
                    return $.extend({}, {
                        query: keyword,
                    });
                },
                noUserMessage: _enumMessage.noUser,
                noKeywordMessage: _enumMessage.noKeyword,
            };
            options = $.extend({}, defaults, options, {
                type: enumFormUnitType.user,
            });
            var template =
                '<table class="table component-table-user-standard mb0" user>' +
                ' <tbody>' +
                '   <tr>' +
                '     <td class="nbd" keyword></td>' +
                '     <td class="nbd" width="100">' +
                '       <button class="btn btn-default common-form-btn" type="button" search>搜索</button>' +
                '     </td>' +
                '   </tr>' +
                ' </tbody>' +
                '</table>';
            createDom.createTemplate(template).attr('form', '').addClass('npd');
            var id = $.getGuid();
            var contentDom = $('.content');
            var userDom = createDom.find('table[user]');
            var keywordDom = createDom.find('td[keyword]');
            var searchDom = createDom.find('.btn[search]');
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            var offsetTop = 0;
            var offsetLeft = 0;
            var userItemTemplate = '' +
                '   <tr data>' +
                '     <td class="nbd vam">' + options.format + '</td>' +
                '     <td class="nbd" width="100">' +
                '       <button class="btn btn-default common-form-btn" type="button" delete>删除</button>' +
                '     </td>' +
                '   </tr>';
            var relevanceListTemplate = '' +
                '<div id="{{id}}" style="position: absolute; height: 200px; overflow: auto;" relevance>' +
                '   <ul class="list-group">' +
                '   </ul>' +
                '</div>';
            var relevanceItemTemplate = '<li class="list-group-item" data>' + options.format + '</li>';
            if ($.isEmpty(domStorage.data(tableName))) {
                if (options.single) domStorage.data(tableName, {});
                else domStorage.data(tableName, []);
            }
            var value = domStorage.data(tableName)[fieldName];
            if (options.single) {
                value = $.toObject(value);
            } else {
                value = $.toArray(value);
            }
            if (options.locked) searchDom.attr('locked', '');
            createDom.data({
                format: options.format,
                domStorage: domStorage,
                fieldValue: fieldValue,
                type: options.user,
                value: [value],
                index: 0,
            });
            searchDom.attr(options.buttonAttributes).prop({
                disabled: options.disabled,
            });
            keywordDom.createString(userDom, 'params.keyword', $.extend({}, options));
            var keywordInputDom = keywordDom.find('input');
            if (!$.isEmpty(value)) {
                if (options.single) {
                    if (options.displayInTextBox) {
                        keywordInputDom.val(value.employeeId + ' / ' + value.chineseName);
                        userDom.data().params.keyword = value.employeeId;
                    }
                    else userDom.find('tbody').createTemplate(userItemTemplate, value);
                } else {
                    if (options.displayInTextBox) {
                        userDom.data().params.keyword = value.employeeId;
                        keywordInputDom.val(value[0].employeeId + ' / ' + value[0].chineseName);
                    }
                    else {
                        for (var i = 0; i < value.length; i++)
                            userDom.find('tbody').createTemplate(userItemTemplate, value[i]);
                    }
                }
            } else {
                if (options.single) {
                    domStorage.data(tableName)[fieldName] = {};
                } else {
                    domStorage.data(tableName)[fieldName] = [];
                }
            }
            setTimeout(function () {
                offsetTop = keywordInputDom.position().top + 40;
                offsetLeft = keywordInputDom.position().left;
            }, 1);
            searchDom.on('click', function () {
                var keyword = userDom.data().params.keyword.split('/')[0].trim();
                if ($.isEmpty(keyword)) return keywordDom.verifyErrorAndHelp(options.noKeywordMessage);
                var getMethodParams = function (keyword) {
                    if ($.isEmpty(options.getMethodParams) || !$.isFunction(options.getMethodParams)) return {};
                    if ($.isEmpty(options.getMethodParams(keyword)) || !$.isObject(options.getMethodParams(keyword))) return {};
                    return options.getMethodParams(keyword);
                }
                var params = $.extend(params, {
                    customMethodName: options.methodName,
                    customMethodParams: getMethodParams(keyword),
                });
                $.post(_apiPath + '/eLancos/customMethod', params)
                    .then(function (data) {
                        if ($.isEmpty(data)) return $.alert(options.noUserMessage);
                        contentDom.createTemplate(relevanceListTemplate, { id: id });
                        contentDom.find(' div[relevance]:last .list-group').createListTemplate(relevanceItemTemplate, data);
                        contentDom.find(' div[relevance]:last').css({
                            top: offsetTop,
                            left: offsetLeft,
                            width: keywordInputDom.outerWidth(),
                        });
                        return false;
                    });
            });
            $('body').on('click', function () {
                if ($('div[relevance]').length != 0) $('div[relevance]').remove();
            });
            $('body').on('click', '#' + id + ' .list-group-item', function () {
                var thisDom = $(this);
                var relevanceListDom = thisDom.parents('div[relevance]');
                var data = thisDom.data().data;
                if (options.single) userDom.find('tbody tr[data]').remove();
                if (options.displayInTextBox) keywordDom.findFormUnit().val(data.employeeId + ' / ' + data.chineseName).trigger('change').verifyClean();
                else userDom.find('tbody').createTemplate(userItemTemplate, data);
                createDom.saveData(data);
                relevanceListDom.remove();
                if (!options.displayInTextBox) keywordDom.findFormUnit().val(null).trigger('change').verifyClean();
                createDom.trigger('selectUserCallback', data);
                return false;
            });
            createDom.on('click', '.btn[delete]', function () {
                var thisDom = $(this);
                thisDom.parents('tr[data]').remove();
                createDom.saveData({});
            });
            createDom.trigger('createCallback');
        });
    },
    createOptionList: function (optionList, firstOption) {
        return this.each(function () {
            var createDom = $(this);
            var optionTemplate = '<option value="{{key}}" data>{{value}}</option>';
            if ($.isEmpty(firstOption)) firstOption = _defaultSelect;
            optionList = [firstOption].concat(optionList);
            createDom.createListTemplate(optionTemplate, optionList);
        });
    },
    createUnit: function (before, after) {
        return this.each(function () {
            var thisDom = $(this);
            var formGroupDom = thisDom.find('.form-group');
            if ($.isEmpty(before) && $.isEmpty(after)) return;
            if (formGroupDom.length == 0) return;
            if (formGroupDom.find('.input-group').length != 0) return;
            formGroupDom.append($('<div>').addClass('input-group col-xs-12'));
            var inputGroupDom = formGroupDom.find('.input-group');
            var formControlDom = thisDom.find('.form-control');
            var icoDom = thisDom.find('.glyphicon');
            inputGroupDom.append(formControlDom);
            if (!$.isEmpty(before)) inputGroupDom.prepend($('<div>').addClass('input-group-addon').html(before));
            if (!$.isEmpty(after)) inputGroupDom.append($('<div>').addClass('input-group-addon').html(after));
            if ($.isEmpty(after)) formControlDom.before(icoDom.css('z-index', 3));
            else formControlDom.after(icoDom.addClass('r40'));
        });
    },
    createListTemplate: function (template, dataList, method, callback) {
        return this.each(function () {
            dataList = $.toArray(dataList);
            method = method || 'append';
            callback = callback || new Function;
            if ($.isFunction(method)) {
                callback = method;
                method = 'append';
            }
            var thisDom = $(this);
            var indexRegexp = /{{@index}}/g;
            var regTemplate;
            for (var i = 0; i < dataList.length; i++) {
                var dataItem = dataList[i];
                regTemplate = template.replace(indexRegexp, i);
                thisDom.createTemplate(regTemplate, dataItem, method);
                callback(dataItem);
            }
        });
    },
    createTemplate: function (template, data, method) {
        return this.each(function () {
            if (typeof Template7 == 'undefined') throw new Error('jQuery extend javascript requires Template7');
            data = $.toObject(data);
            if (!$.isObject(data)) return console.error('create template function data must be Object');
            var thisDom = $(this);
            method = method || 'append';
            thisDom[method](Template7.compile(template)(data));
            thisDom.find('>*[data]:last').data('data', data);
        });
    },
    showMask: function () {
        return this.each(function () {
            var thisDom = $(this);
            var position = 'absolute';
            var template =
                '<div mask style="position: {{position}}; z-index: 9999; top: 0; bottom: 0; left: 0; right: 0; background: rgba(000, 000, 000, 0.5);">' +
                '   <i class="fa fa-spinner fa-pulse" style="position: absolute; top: 50%; left: 50%; margin: -40px 0 0 -40px; font-size: 80px; color: #FFF;"></i>' +
                '</div>';;
            if (thisDom.is('html') || thisDom.is('body')) position = 'fixed';
            else thisDom.addClass('por');
            thisDom.createTemplate(template, {
                position: position,
            });
        });
    },
    hideMask: function () {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.find('>[mask]').remove().removeClass('por');
        });
    },
    createIconRadio: function (domStorage, fieldValue, fieldText, groupList, options) {
        return this.each(function () {
            if ($.isArray(fieldText)) {
                options = groupList;
                groupList = fieldText;
                fieldText = '';
            }
            var createDom = $(this);
            var defaults = {
                type: enumFormUnitType.radio,
                locked: createDom.is('[locked]'),
                disabled: false,
                attributes: {},
            };
            var createDomRequired = createDom[0].id + '-required';
            options = $.extend({}, defaults, options);
            var guid = $.getGuid();
            var tableName = fieldValue.split('.')[0];
            var fieldName = fieldValue.split('.')[1];
            var template = `<div class="mb0">`;
            for (var i = 0; i < groupList.length; i++) {
                template += `<div class="fll">
                <input type="radio" value="`+ groupList[i].value + `" name="${fieldName}" class="dn" id="${fieldName + i}">
                <label class="pr10" for="${fieldName + i}" style="width: 40px;height: 40px">
                    <img src="/asstes/images/radio1.png" width="40" height="40" class="fll" id="img`+ groupList[i].key + `"></img>
                </label>
                <span class="flr db mt10 pr50 pl15">`+ groupList[i].value + `</span>
                </div>`
            }
            template += `<span id="${createDomRequired}"></span></div>`;
            createDom.createTemplate(template).attr('form', '');
            var radioListDom = createDom.find(':radio');
            if ($.isEmpty(domStorage.data(tableName))) domStorage.data(tableName, {});
            var value = $.htmlDecode(domStorage.data(tableName)[fieldName]);
            if (options.locked) selectDom.attr('locked', '');
            createDom.data({
                domStorage: domStorage,
                fieldValue: fieldValue,
                fieldText: fieldText,
                type: options.type,
                value: [],
                text: [],
                index: 0,
            });
            radioListDom.filter('[value=' + value + ']').prop('checked', true);
            radioListDom.attr(options.attributes);
            if ($.isBoolean(options.disabled)) radioListDom.prop('disabled', options.disabled);
            if ($.isArray(options.disabled))
                for (var i = 0; i < options.disabled.length; i++)
                    radioListDom.eq(options.disabled[i]).prop('disabled', true).parent().addClass('disabled');
            radioListDom.on('change', function () {
                $(`#${createDomRequired}`).html('');
                var thisDom = $(this);
                var isChecked = thisDom.is(':checked');
                var value = $.toString(thisDom.val());
                var text = $.toString(thisDom.parent('[input]').context.value);
                if (!isChecked) return;
                createDom.saveData(value, text);
                createDom.trigger('changeCallback', value);
                if ($.toSringReturnBoolean(groupList[0].value, groupList[1].value, value)) {
                    $("#img" + groupList[0].key).attr('src', `/asstes/images/radio0.png`);
                    $("#img" + groupList[1].key).attr('src', `/asstes/images/radio1.png`);
                } else {
                    $("#img" + groupList[0].key).attr('src', `/asstes/images/radio1.png`);
                    $("#img" + groupList[1].key).attr('src', `/asstes/images/radio0.png`);
                }
            });
            if (_data.formDetail.formDetail[fieldName] === "true") {
                domStorage.data(tableName)[fieldName] = groupList[0].value;
                $("#img" + groupList[0].key).attr('src', `/asstes/images/radio0.png`);
                $("#img" + groupList[1].key).attr('src', `/asstes/images/radio1.png`);
            }
            if (_data.formDetail.formDetail[fieldName] === "false") {
                domStorage.data(tableName)[fieldName] = groupList[1].value;
                $("#img" + groupList[0].key).attr('src', `/asstes/images/radio1.png`);
                $("#img" + groupList[1].key).attr('src', `/asstes/images/radio0.png`);
            }
            // radioListDom.eq(0).prop('checked', true).trigger('change').verifyClean();
            createDom.trigger('createCallback');
        });
    },
});

$.fn.extend({
    verifySuccess: function (delay) {
        return this.each(function () {
            delay = delay || 2000;
            var thisDom = $(this);
            var icoDom = thisDom.siblings('.glyphicon');
            var parentDom = thisDom.parents('.form-group');
            icoDom.addClass('glyphicon-ok').removeClass('glyphicon-remove');
            parentDom.addClass('has-success has-feedback').removeClass('has-error');
            setTimeout(function () {
                if (!parentDom.hasClass('has-error')) parentDom.removeClass('has-success has-feedback');
                icoDom.removeClass('glyphicon-ok');
            }, delay);
        });
    },
    verifyError: function () {
        return this.each(function () {
            var thisDom = $(this);
            var icoDom = thisDom.siblings('.glyphicon');
            var parentDom = thisDom.parents('.form-group');
            icoDom.addClass('glyphicon-remove').removeClass('glyphicon-ok');
            parentDom.addClass('has-error has-feedback').removeClass('has-success');
        });
    },
    verifyClean: function () {
        return this.each(function () {
            var thisDom = $(this);
            var parentDom = thisDom.parents('.form-group');
            var icoDom = thisDom.siblings('.glyphicon');
            parentDom.removeClass('has-error has-feedback has-success');
            icoDom.removeClass('glyphicon-remove glyphicon-ok');
            parentDom.find('.help-block').remove();
        });
    },
    verifyHelp: function (message) {
        return this.each(function () {
            var thisDom = $(this);
            if (thisDom.parents('*[form]').find('.input-group').length == 0)
                thisDom.after($('<span>').text(message).addClass('help-block mb0'));
            else
                thisDom.parents('*[form]').eq(0).find('.input-group').after($('<span>').text(message).addClass('help-block mb0'));
        });
    }
});

$.fn.extend({
    saveData: function (value, text) {
        return this.each(function () {
            var thisDom = $(this);
            var data = thisDom.data();
            if (data.type == enumFormUnitType.doubleDate) return;
            var tableName = data.fieldValue.split('.')[0];
            var fieldName = data.fieldValue.split('.')[1];
            data.value.push(value);
            data.domStorage.data(tableName)[fieldName] = value;
            if (!$.isEmpty(data.fieldText)) {
                var tableName = data.fieldText.split('.')[0];
                var fieldName = data.fieldText.split('.')[1];
                data.text.push(text);
                data.domStorage.data(tableName)[fieldName] = text;
            }
            data.index = data.value.length - 1;
        });
    },
    resetData: function () {
        return this.each(function () {
            var thisDom = $(this);
            var data = thisDom.data();
            thisDom.gotoData(0);
            if (data.type == enumFormUnitType.doubleDate) return;
            thisDom.findFormUnit().trigger('change').trigger('changeData');
            data.value = data.value.splice(0, 1);
            data.index = 0;
        });
    },
    nextData: function () {
        return this.each(function () {
            var thisDom = $(this);
            var data = thisDom.data();
            var targetIndex = data.index + 1 > data.value.length - 1 ? data.value.length - 1 : data.index + 1;
            thisDom.gotoData(targetIndex);
        });
    },
    prevData: function () {
        return this.each(function () {
            var thisDom = $(this);
            var data = thisDom.data();
            var targetIndex = data.index - 1 < 0 ? 0 : data.index - 1;
            thisDom.gotoData(targetIndex);
        });
    },
    gotoData: function (targetIndex) {
        return this.each(function () {
            var thisDom = $(this);
            var data = thisDom.data();
            if (data.type == enumFormUnitType.string ||
                data.type == enumFormUnitType.email ||
                data.type == enumFormUnitType.mobile ||
                data.type == enumFormUnitType.telephone ||
                data.type == enumFormUnitType.integer ||
                data.type == enumFormUnitType.decimal ||
                data.type == enumFormUnitType.select ||
                data.type == enumFormUnitType.inputSelect ||
                data.type == enumFormUnitType.radio ||
                data.type == enumFormUnitType.textarea) {
                thisDom.findFormUnit().val(data.value[targetIndex]).trigger('change').verifyClean();
                data.value = data.value.splice(0, data.value.length - 1);
                if (!$.isEmpty(data.text)) data.text = data.text.splice(0, data.text.length - 1);
            } else if (data.type == enumFormUnitType.date) {
                thisDom.findFormUnit().val(data.value[targetIndex]).trigger('changeDate').verifyClean();
                data.value = data.value.splice(0, data.value.length - 1);
            } else if (data.type == enumFormUnitType.doubleDate) {
                thisDom.parents('[form]').find('td[form] input').datepicker('hide');
            } else if (data.type == enumFormUnitType.checkbox) {
                var checkboxListDom = thisDom.find('input');
                var allSelectedDom = checkboxListDom.filter('[value=' + _allSelect.key + ']');
                var valueList = data.value[targetIndex];
                checkboxListDom.prop('checked', false);
                for (var i = 0; i < valueList.length; i++)
                    for (var j = 0; j < checkboxListDom.length; j++)
                        if (valueList[i] == checkboxListDom.eq(j).val()) checkboxListDom.eq(j).prop('checked', true);
                if (checkboxListDom.length - 1 == checkboxListDom.filter(':not([value=' + _allSelect.key + '])').filter(':checked').length) allSelectedDom.prop('checked', true);
                else allSelectedDom.prop('checked', false);
            } else if (data.type == enumFormUnitType.singleCheckbox) {
                var checkboxDom = thisDom.find('input');
                if (data.isNumber && data.reverse && $.isZero(data.value[targetIndex]) ||
                    data.isNumber && !data.reverse && !$.isZero(data.value[targetIndex]) ||
                    !data.isNumber && data.reverse && !data.value[targetIndex] ||
                    !data.isNumber && !data.reverse && data.value[targetIndex]) checkboxDom.prop('checked', true);
                else checkboxDom.prop('checked', false);
            } else if (data.type == enumFormUnitType.attachment) {
                var attachmentDom = thisDom.find('.table-attachment tbody');
                var dataList = data.value[targetIndex];
                var template = data.template;
                attachmentDom.empty().createListTemplate(template, dataList);
            }
            data.index = targetIndex;
        });
    }
});

$.fn.extend({
    resetForm: function () {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.find('input, select, textarea').parents('*[form]').resetData(0).verifyClean();
        });
    },
    disabledForm: function (locked) {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.find('input, select, textarea, button').filter(':not([locked])').prop('disabled', true);
        });
    },
    enabledForm: function () {
        return this.each(function () {
            var thisDom = $(this);
            thisDom.find('input, select, textarea, button').filter(':not([locked])').prop('disabled', false);
        });
    },
});

$.fn.extend({
    findFormUnit: function () {
        return this.find('input, select, textarea');
    },
});

$.extend({
    isEmpty: function (value) {
        if (value == null || value == undefined) return true;
        if ($.isString(value) && value.trim().length == 0) return true;
        else if ($.isArray(value) && value.length == 0) return true;
        else if ($.isObject(value) && JSON.stringify(value) == '{}') return true;
        return false;
    },
    isString: function (value) {
        return value != null && value != undefined && value.constructor == String;
    },
    isNumber: function (value) {
        return value != null && value != undefined && value.constructor == Number;
    },
    isBoolean: function (value) {
        return value != null && value != undefined && value.constructor == Boolean;
    },
    isArray: function (value) {
        return value != null && value != undefined && value.constructor == Array;
    },
    isObject: function (value) {
        return value != null && value != undefined && value.constructor == Object;
    },
    isJSON: function (value) {
        if ($.isEmpty(value)) return false;
        if ($.isArray(value) || $.isObject(value)) return true;
        return false;
    },
    isFunction: function (value) {
        return value != null && value != undefined && value.constructor == Function;
    },
    isEmail: function (value) {
        return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
    },
    isZero: function (value) {
        if ($.isEmpty(value)) return false;
        return value == 0;
    },
    isInteger: function (value, range) {
        range = $.toString(range) || '+';
        if (range.indexOf('-') != -1 && /^-[1-9]\d*$/.test(value)) return true;
        else if (range.indexOf('0') != -1 && $.isZero(value)) return true;
        else if (range.indexOf('+') != -1 && /^[1-9]\d*$/.test(value)) return true;
        return false;
    },
    isDecimal: function (value, digit, range) {
        digit = $.toNumber(digit) || 2;
        range = $.toString(range) || '+';
        if (range.indexOf('-') != -1 && new RegExp('^-[0-9]+([.]{1}[0-9]{1,' + digit + '})?$').test(value)) return true;
        if (range.indexOf('0') != -1 && $.isZero(value)) return true;
        if (range.indexOf('+') != -1 && new RegExp('^[0-9]+([.]{1}[0-9]{1,' + digit + '})?$').test(value)) return true;
        return false;
    },
    isMobile: function (value) {
        return true;
    },
    isTelephone: function (value) {
        return true;
    },
});

$.extend({
    toString: function (value) {
        if ($.isEmpty(value)) return '';
        if ($.isJSON(value)) return JSON.stringify(value);
        return $.htmlEncode(String(value));
    },
    toNumber: function (value) {
        if ($.isEmpty(value)) return '';
        return Number(value);
    },
    toBoolean: function (value) {
        return Boolean(eval(value));
    },
    toArray: function (value) {
        if ($.isEmpty(value) || !$.isArray(value)) return [];
        return value;
    },
    toObject: function (value) {
        if ($.isEmpty(value) || !$.isObject(value)) return {};
        return value;
    },
    toDate: function (value) {
        if ($.isEmpty(value)) return '';
        return $.toString(value).split('T')[0];
    },
    toJSON: function (value) {
        if ($.isEmpty(value)) return {};
        return JSON.parse(value);
    },
    toInteger: function (value, isCutoff) {
        if ($.isEmpty(value)) return '';
        isCutoff = isCutoff || false;
        if (isCutoff) return $.toNumber($.toString(value).split('.')[0]);
        return value.toFixed(0);
    },
    toDecimal: function (value, digit, isCutoff) {
        if ($.isEmpty(value)) return '';
        isCutoff = isCutoff || false;
        digit = digit || 2;
        if (isCutoff) return $.toNumber($.toString(value).split('.')[0] + $.toString(value).split('.')[1].substring(0, digit));
        return value.toFixed(digit);
    },
    toMoney: function (value) {
        var symbol = value < 0 ? '-' : '';
        if ($.isEmpty(value)) return '';
        if ($.isNumber(value) == 0) return '0';
        if ($.toNumber(value) < 0) value = Math.abs(value);
        if ($.toString(value).indexOf('.') != -1) return symbol + $.toString(value).split('.')[0].split('').reverse().join('').replace(/(\d{3})/g, '$1,').replace(/\,$/, '').split('').reverse().join('') + '.' + $.toString(value).split('.')[1];
        return symbol + $.toString(value).split('').reverse().join('').replace(/(\d{3})/g, '$1,').replace(/\,$/, '').split('').reverse().join('');
    },
    numberToAccount: function (value) {
        return accounting.formatMoney(value, [symbol = ""], [precision = 2], [thousand = ","], [decimal = "."], [format = "%s%v"]);
    },
    accountToNumber: function (value) {
        return accounting.formatNumber(value, 2, "", ".")
    },
    toPercent: function (value, digit) {
        if ($.isEmpty(value)) return '';
        var symbol = value < 0 ? '-' : '';
        value = Math.abs($.toNumber(value));
        digit = digit || 1;
        digit = 100 * Math.pow(10, digit);
        value = symbol + $.mathCheng($.mathChu(Math.floor($.mathCheng(value, digit)), digit), 100);
        return $.toNumber(value);
    },
    toSize: function (value) {
        if ($.isEmpty(value) || $.isZero(value)) return '0 B';
        var k = 1024;
        var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
        i = Math.floor(Math.log(value) / Math.log(k));
        return (value / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
    },
    toSringReturnBoolean: function (str1, str2, value) {
        if (str1 == value) return true;
        if (str2 == value) return false;
        return '';
    }
});

$.extend({
    getGuid: function () {
        var _guid = '';
        for (var i = 1; i <= 32; i++) {
            var n = Math.floor(Math.random() * 16.0).toString(16);
            _guid += n;
            if ((i == 8) || (i == 12) || (i == 16) || (i == 20)) _guid += '-';
        }
        return _guid;
    },
    getParam: function (key) {
        var value = window.location.search.substr(1).match(new RegExp('(^|&)' + key + '=([^&]*)(&|$)', 'i'));
        if ($.isEmpty(value)) return '';
        return unescape(value[2]);
    },
    getUserAuthorityList: function (userRoleList, authorityList, pageList) {
        if ($.isEmpty(userRoleList)) return [];
        var _userAuthorityList = [];
        var allPageIDList = $.getUserAllPageIDList(userRoleList, authorityList);
        var allPageList = $.getUserAllPageList(allPageIDList, pageList);
        _userAuthorityList = $.getAuthorityList(allPageList);
        return _userAuthorityList;
    },
    getUserAllPageIDList: function (userRoleList, authorityList) {
        var _pageIDList = [];
        for (var i = 0; i < authorityList.length; i++) {
            if (userRoleList.indexOf(authorityList[i].role) > -1) {
                _pageIDList = _pageIDList.concat(authorityList[i].pageList);
            }
        }
        // for (var j = 0; j < userRoleList.length; j++) {
        //     if (authorityList[i].role == userRoleList[j]) _pageIDList = _pageIDList.concat(authorityList[i].pageList);
        // }
        return _pageIDList;
    },
    getUserAllPageList: function (allPageIDList, pageList) {
        var _pageList = [];
        for (var i = 0; i < allPageIDList.length; i++)
            for (var j = 0; j < pageList.length; j++)
                if (allPageIDList[i] == pageList[j].id) _pageList.push(pageList[j]);
        return _pageList;
    },
    getAuthorityList: function (allPageList) {
        var _authorityList = [];
        var pageList = $.extend([], allPageList);
        var IDList = [];
        var orderList = [];
        for (var i = 0; i < pageList.length; i++) {
            var isRepeat = false;
            for (var j = 0; j < _authorityList.length; j++) {
                if (i != j && pageList[i].id == _authorityList[j].id) isRepeat = true;
            }
            if (!isRepeat) _authorityList.push(pageList[i]);
        }
        _authorityList.sort(function (object1, object2) {
            if (object1.order < object2.order) return -1;
            else if (object1.order > object2.order)
                return 1;
            else return 0;
        });
        return _authorityList;
    },
    getCurrentPage: function (pageList) {
        var currentUrl = window.location.href.toLowerCase();
        for (var i = 0; i < pageList.length; i++)
            if (currentUrl.indexOf(pageList[i].href.toLowerCase()) != -1) return pageList[i];
        return {};
    },
    getFilterList: function (listData, filter) {
        if ($.isEmpty(filter)) return listData;
        var _array = [];
        for (var i = 0; i < listData.length; i++) {
            var itemData = listData[i];
            var judge = true;
            for (var key in filter)
                if (filter[key] != itemData[key]) judge = false;
            if (judge) _array.push(itemData);
        }
        return _array;
    },
    getKeyValueList: function (key, value, listData) {
        var _keyValueList = [];
        for (var i = 0; i < listData.length; i++) _keyValueList.push({
            key: listData[i][key],
            value: listData[i][value],
            data: listData[i],
        });
        return _keyValueList;
    },
    getKeyValueListByObject: function (object) {
        var list = []
        for (var key in object) {
            list.push({ key: object[key], value: key });
        }
        return list;
    },
    getPageConfig: function (id, listData) {
        var _pageConfig = $.getFilterList(listData, { id: id });
        if ($.isEmpty(_pageConfig)) return {};
        return _pageConfig[0];
    },
    getUrlParams: function (url, value) {
        if (value) {
            var reg = new RegExp(`(^|&)${value}=([^(&|#)]*)`, 'g');
            var msgArr = url;
            if (url.indexOf('?') > -1) {
                msgArr = url.split('?')[1].match(reg);
            }
            if (!msgArr) return '';
            for (var i = 0; i < msgArr.length; i++) {
                msgArr[i] = msgArr[i].substr(1).replace(/\w+=/, '');
            }
            if (msgArr.length == 1) {
                return msgArr[0];
            }
            return msgArr;
        } else {
            var reg = new RegExp(`(^|&)${value}=([^(&|#)]*)`, 'g');
            var msgArr = url;
            if (url.indexOf('?') > -1) {
                msgArr = url.split('?')[1].match(reg);
            }
            if (!msgArr) return '';
            for (var i = 0; i < msgArr.length; i++) {
                msgArr[i] = msgArr[i].substr(1).replace(/\w+=/, '');
            }
            if (msgArr.length == 1) {
                return msgArr[0];
            }
            return msgArr;
        }
    },
});

$.extend({
    createCookie: function (key, value, days) {
        var expires = '';
        if ($.isEmpty(days)) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = '; expires=' + date.toGMTString();
        }
        document.cookie = key + '=' + value + expires + '; path=/';
    },
    getCookie: function (key) {
        key += '=';
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i];
            while (cookie.charAt(0) == ' ') cookie = cookie.substring(1, cookie.length);
            if (cookie.indexOf(key) == 0) return cookie.substring(key.length, cookie.length);
        }
        return '';
    },
    deleteCookie: function (key) {
        var date = new Date();
        date.setTime(date.getTime() - 1);
        var cookie = $.getCookie(key);
        if (!$.isEmpty(cookie)) document.cookie = name + '=' + cval + "; expires=" + date.toGMTString();
    },
});

$.extend({
    base64Encode: function (value) {
        var keyString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
        var encode = '';
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
        value = $.utf8Encode(value);
        while (i < value.length) {
            chr1 = value.charCodeAt(i++);
            chr2 = value.charCodeAt(i++);
            chr3 = value.charCodeAt(i++);
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if ($.isEmpty(chr2)) enc3 = enc4 = 64;
            else if ($.isEmpty(chr3)) enc4 = 64;
            encode += keyString.charAt(enc1) + keyString.charAt(enc2) + keyString.charAt(enc3) + keyString.charAt(enc4);
        }
        return encode;
    },
    base64Decode: function (value) {
        var keyString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
        var decode = '';
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;
        value = value.replace(/[^A-Za-z0-9\+\/\=]/g, '');
        while (i < value.length) {
            enc1 = keyString.indexOf(value.charAt(i++));
            enc2 = keyString.indexOf(value.charAt(i++));
            enc3 = keyString.indexOf(value.charAt(i++));
            enc4 = keyString.indexOf(value.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            decode = decode + String.fromCharCode(chr1);
            if (enc3 != 64) decode += String.fromCharCode(chr2);
            if (enc4 != 64) decode += String.fromCharCode(chr3);
        }
        decode = $.utf8Decode(decode);
        return decode;
    },
    utf8Encode: function (value) {
        value = value.replace(/\r\n/g, '\n');
        var encode = '';
        for (var i = 0; i < value.length; i++) {
            var c = value.charCodeAt(i);
            if (c < 128) encode += String.fromCharCode(c);
            else if ((c > 127) && (c < 2048)) encode += String.fromCharCode((c >> 6) | 192) + String.fromCharCode((c & 63) | 128);
            else encode += String.fromCharCode((c >> 12) | 224) + String.fromCharCode(((c >> 6) & 63) | 128) + String.fromCharCode((c & 63) | 128);
        };
        return encode;
    },
    utf8Decode: function (value) {
        var decode = '';
        var i = 0;
        var c = c1 = c2 = 0;
        while (i < value.length) {
            c = value.charCodeAt(i);
            if (c < 128) {
                decode += String.fromCharCode(c);
                i++;
            } else if ((c > 191) && (c < 224)) {
                c2 = value.charCodeAt(i + 1);
                decode += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            } else {
                c2 = value.charCodeAt(i + 1);
                c3 = value.charCodeAt(i + 2);
                decode += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            };
        }
        return decode;
    },
    htmlEncode: function (value) {
        return $('<div>').text(value).html();
    },
    htmlDecode: function (value) {
        return $('<div>').html(value).text();
    },
});

$.extend({
    mathJia: function (number01, number02) {
        var r1, r2, m, c;
        try {
            r1 = number01.toString().split('.')[1].length
        } catch (e) {
            r1 = 0;
        };
        try {
            r2 = number02.toString().split('.')[1].length
        } catch (e) {
            r2 = 0;
        };
        c = Math.abs(r1 - r2);
        m = Math.pow(10, Math.max(r1, r2))
        if (c > 0) {
            var cm = Math.pow(10, c);
            if (r1 > r2) {
                number01 = Number(number01.toString().replace('.', ''));
                number02 = Number(number02.toString().replace('.', '')) * cm;
            } else {
                number01 = Number(number01.toString().replace('.', '')) * cm;
                number02 = Number(number02.toString().replace('.', ''));
            };
        } else {
            number01 = Number(number01.toString().replace('.', ''));
            number02 = Number(number02.toString().replace('.', ''));
        };
        return (number01 + number02) / m;
    },
    mathJian: function (number01, number02) {
        var r1, r2, m, n;
        try {
            r1 = number01.toString().split('.')[1].length;
        } catch (e) {
            r1 = 0;
        };
        try {
            r2 = number02.toString().split('.')[1].length
        } catch (e) {
            r2 = 0;
        };
        m = Math.pow(10, Math.max(r1, r2));
        n = (r1 >= r2) ? r1 : r2;
        return ((number01 * m - number02 * m) / m).toFixed(n);
    },
    mathCheng: function (number01, number02) {
        var m = 0,
            s1 = number01.toString(),
            s2 = number02.toString();
        try {
            m += s1.split('.')[1].length;
        } catch (e) { };
        try {
            m += s2.split('.')[1].length;
        } catch (e) { };
        return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m);
    },
    mathChu: function (number01, number02) {
        var t1 = 0,
            t2 = 0,
            r1, r2;
        try {
            t1 = number01.toString().split('.')[1].length;
        } catch (e) { };
        try {
            t2 = number02.toString().split('.')[1].length;
        } catch (e) { };
        with (Math) {
            r1 = Number(number01.toString().replace('.', ''));
            r2 = Number(number02.toString().replace('.', ''));
            return (r1 / r2) * pow(10, t2 - t1);
        };
    },
});

$.extend({
    goto: function (href, target) {
        target = target || '_self';
        //$('<a>').attr('href', href).attr('target', target)[0].click();
        window.location.href = href;
    },
});

Template7.registerHelper('format', function (string, formatList, options) {
    if ($.isEmpty(options)) options = formatList;
    if (!$.isString(formatList)) return $.toString(string);
    formatList = formatList.replace(/\s/g, '').split('|');
    for (var i = 0; i < formatList.length; i++) {
        var formatItem = formatList[i];
        if (formatItem.indexOf(':') == -1) {
            if ($.isEmpty(formatItem) || !$.isFunction(eval(formatItem))) continue;
            string = eval(formatItem)(string);
        } else {
            var functionName = formatItem.split(':')[0];
            if ($.isEmpty(functionName) || !$.isFunction(eval(functionName))) continue;
            var paramList = formatItem.split(':');
            var express = 'string = ' + functionName + '(string';
            for (var i = 1; i < paramList.length; i++)
                express += ', ' + paramList[i];
            express += ')';
            eval(express);
        }
    }
    return string;
});

Number.prototype.toFixed = function (digit) {
    var symbol = this < 0 ? '-' : '';
    var number = symbol + (parseInt(Math.abs(this) * Math.pow(10, digit) + 0.5) / Math.pow(10, digit)).toString();
    var index = number.indexOf('.');
    var limit = digit;
    if (index < 0 && digit > 0) (number = number + '.') && (limit = digit);
    else (index = number.length - index) && (limit = digit - index);
    for (var i = 0; i < limit; i++) number += '0';
    return number;
}

if (!window.location.origin) window.location.origin = window.location.protocol + '//' + window.location.hostname + (window.location.port ? ':' + window.location.port : '');

function BaseFrame() {
    this.load = new BaseChildFrame();
    this.load.start = new Function;
    this.form = new BaseChildFrame();
    this.event = new BaseChildFrame();
    this.save = new BaseChildFrame();
    this.verify = new BaseChildFrame();
    this.message = new BaseChildFrame();
    this.data = new BaseChildFrame();
}
BaseFrame.prototype.addBlock = function () {
    var blockList = arguments;
    for (var i = 0; i < blockList.length; i++) {
        var blockItem = blockList[i];
        if ($.isString(blockItem)) {
            this.load[blockItem] = new BaseChildFrame();
            this.load._task.push(this.load[blockItem].runTask);
            this.event[blockItem] = new BaseChildFrame();
            this.event._task.push(this.event[blockItem].runTask);
            this.save[blockItem] = new BaseChildFrame();
            this.verify[blockItem] = new BaseChildFrame();
            this.message[blockItem] = new BaseChildFrame();
            this.data[blockItem] = new BaseChildFrame();
        }
    }
}
BaseFrame.prototype.addBind = function (key, value) {
    this[key] = value;
    this._task.push(this[key]);
}
BaseFrame.prototype.addEvent = function (key, value) {
    this[key] = value;
}
BaseFrame.prototype.addConfig = function (key, value) {
    this[key] = value;
}

function BaseChildFrame() {
    this.runTask = this.runTask.bind(this);
    this._task = [];
}
BaseChildFrame.prototype.addStart = function (startFunction) {
    this.start = startFunction;
}
BaseChildFrame.prototype.runTask = function () {
    var taskList = this._task;
    for (var i = 0; i < taskList.length; i++)
        if ($.isFunction(taskList[i])) taskList[i]();
}
BaseChildFrame.prototype.addBind = function (key, value) {
    this[key] = value;
    this._task.push(this[key]);
}
BaseChildFrame.prototype.addEvent = function (key, value) {
    this[key] = value;
}
BaseChildFrame.prototype.addConfig = function (key, value) {
    this[key] = value;
}
Date.prototype.addDays = function (value) {
    var dat = new Date(this.valueOf());
    this.setDate(dat.getDate() + value);
    return;
}